
package com.ys.chatserver.http.file.d;

import com.alibaba.fastjson.JSONObject;
import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.httpfile.FileDownload;
import com.eva.framework.utils.LoggerFactory;
import com.ys.chatserver.BaseConf;
import com.ys.chatserver.http.logic.LogicProcessor2;
import com.ys.chatserver.http.logic.filter.JwtHelper;
import com.ys.chatserver.http.logic.filter.JwtParam;
import com.ys.chatserver.tool.EmptyUtils;
import com.ys.chatserver.tool.MD5Util;
import org.slf4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

//FIXME: 在更苛刻的安全性要求下，可考虑要求客户端把token字段带上来，以便进行更强的合法身份检查
public class UserAvatarDownloader extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    private static final Logger logger = LoggerFactory.getLog();

    /**
     * 一个1像素透明图片
     */
    public final static String ONE_PIXEL_TRANSPARENT_AVATAR_FILE_NAME = "on_pixel_transparent_avatar.png";

    /* (non-Java-doc)
     * @see javax.servlet.http.HttpServlet#HttpServlet()
     */
    public UserAvatarDownloader() {
        super();
    }

    /**
     * Servlet规范中本protected方法由public void service(,,)方法调用, 而public void service(,,)
     * 则由Web容器调用(所以它是public公共方法),因此一般情况下尽量避免重写public void service(,,)方法
     * ,而重写父类的本protedted方法则比较合理.
     */
    protected void service(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {

        LoggerFactory.getLog().debug("[HTTP]下载头像：你传过来的参数" +
                "action=" + req.getParameter("action")
                + ",user_local_cached_avatar=" + req.getParameter("user_local_cached_avatar")
                + ",enforceDawnload=" + req.getParameter("enforceDawnload")
                + ",one_pixel_transparent_if_no=" + req.getParameter("one_pixel_transparent_if_no")
                + ",[---- " + req.getContextPath() + "-" + req.getRequestURL() + "]");

        String action = req.getParameter("action");
        String token = req.getHeader("token");
        String time = req.getHeader("time");
        String authToken = req.getHeader("authToken");
        String path = String.format("/api/%s?%s", getServletName(), req.getQueryString());
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        map.put("time", time);
        map.put("path", path);
        String s = MD5Util.MD5_32(JSONObject.toJSONString(map));
        if (authToken == null) {
            return;
        }
        if (!authToken.equals(s)) {
            return;
        }
        if (EmptyUtils.isNotEmpty(token)) { //token校验
            JwtParam jwtParam = JwtHelper.parseJwt(token);
            String userUid = jwtParam.getUserId();
            try {
                if (JwtHelper.tokenAuth(jwtParam)) {
                    // avatar download
                    if ("ad".equals(action)) {
                        String userLocalCachedAvatarFileName = req.getParameter("user_local_cached_avatar");

                        // 是否强制下载（强制下载意味着无论用户头像用无缓存至本地，都将无条件返回该用户头像（前提是该用 户头像确实存在于服务器上））
                        String _enforceDawnload = req.getParameter("enforceDawnload");
                        boolean enforceDawnload = (_enforceDawnload != null && _enforceDawnload.equals("1"));

                        // 此参数为“1”时，表示当用户没有设置头像时，会默认返回一个1像素透明图片（这主要用于Web网页里显示用户
                        // 头像时，否则当用户没有设置头像时，因为没有图片数据返回而会在页面上显示一个“破图”img元素，那就难看
                        // 死了！）
                        String _onePixelTransparentIfNo = req.getParameter("one_pixel_transparent_if_no");
                        boolean onePixelTransparentIfNo = (_onePixelTransparentIfNo != null && _onePixelTransparentIfNo.equals("1"));

                        processAvatarDownload(res, userUid
                                , userLocalCachedAvatarFileName, enforceDawnload, onePixelTransparentIfNo);
                    } else {
                        LoggerFactory.getLog().warn("[HTTP]无效的action=" + action);
                        logger.error("无权限访问");
                    }
                }
            } catch (Exception e) {
                logger.error("无权限访问");
            }
        } else {
            logger.error("无权限访问");
        }

    }

    /**
     * 用户头像HTTP下载实现方法.
     *
     * @param userLocalCachedAvatarFileName 用户缓存在本地的头像文件名（本参数只在enforceDawnload==false时有意义）
     * @param enforceDawnload               true表示无论客户端有无提交缓存图片名称本方法都将无条件返回该用户头像（如果头像确实存在的话），否则
     *                                      将据客户端提交上来的可能的本地缓存文件来判断是否需要下载用户头像（用户头像没有被更新过当然就不需要下载了！）
     * @param onePixelTransparentIfNo       此参数为“true”时，表示当用户没有设置头像时，会默认返回一个1像素透明图片（这主要用于Web网
     *                                      页里显示用户头像时，否则当用户没有设置头像时，因为没有图片数据返回而会在页面上显示一个“破图”img元素，那就难看死了！）
     */
    private void processAvatarDownload(HttpServletResponse res
            , String userUid, String userLocalCachedAvatarFileName
            , boolean enforceDawnload, boolean onePixelTransparentIfNo) throws IOException {
        String avatarCurrentFileName = null;
        try {
            avatarCurrentFileName = LogicProcessor2.db.querySingleItem(
                    "Select user_avatar_file_name from g_users where del_flag = 0 and user_uid='" + userUid + "'");

            boolean avatarNotExsitsOrNotSetup = true;

            // 头像文件名不为空，即表示此用户设置过头像，为用户下载此头像文件即可
            if (!CommonUtils.isStringEmpty(avatarCurrentFileName, true)) {
                LoggerFactory.getLog().info("[HTTP]用户【" + userUid + "】的头像已被设置过，头像文件名：" + avatarCurrentFileName);

                // 如果不是强迫下载（即客户端有缓存机制情况但看服务端头像是否更新的情况）
                if (!enforceDawnload && userLocalCachedAvatarFileName != null) {
                    // 客户端当前缓存着的用户头像跟数据库里是一样的，就意味着该用户没有更新过头像，不需要重新返回逻
                    if (userLocalCachedAvatarFileName.toLowerCase().equals(avatarCurrentFileName)) {
                        LoggerFactory.getLog().info("[HTTP]用户【" + userUid + "】缓存在本地的头像" + avatarCurrentFileName + "已是最新的，无需下载.");
                        avatarNotExsitsOrNotSetup = false;
                        return;
                    }
                }

                String fileFullPath = BaseConf.getInstance().getDIR_USER_AVATAR_UPLOAD() + avatarCurrentFileName;

                if (!com.eva.epc.common.file.FileHelper.isFileExist(fileFullPath) && onePixelTransparentIfNo) {
                    avatarNotExsitsOrNotSetup = true;
                    LoggerFactory.getLog().info("[HTTP]用户【" + userUid + "】的头像文件" + avatarCurrentFileName
                            + "并不存在！接下将提供默认的1像素透明图片作为默认图，保证web端显示时不会太丑！");
                } else {
                    LoggerFactory.getLog().info("[HTTP]用户【" + userUid + "】缓存在本地的头像" + userLocalCachedAvatarFileName
                            + "(null表示用户本地无缓存)需要更新，下载立即开始 ......");
                    // 实施用户头像下载
                    FileDownload.download(res
                            , BaseConf.getInstance().getDIR_USER_AVATAR_UPLOAD() + avatarCurrentFileName
                            , avatarCurrentFileName
                            , FileDownload.CONTENT_TYPE_JPEG
                            , false);

                    avatarNotExsitsOrNotSetup = false;

                    return;
                }
            }

            // 此用户没有设置过头像或者已设置过但头像文件不存在于服务器磁盘上（这一般是迁移数据时忘记迁移图片文件了）
            if (avatarNotExsitsOrNotSetup)
//			else
            {
                LoggerFactory.getLog().warn("[HTTP]对不起,用户【" + userUid + "】的头像(avatarCurrentFileName=" + avatarCurrentFileName + ")不存在！");

                // 此参数为“true”时，表示当用户没有设置头像时，会默认返回一个1像素透明图片（这主要
                // 用于Web网页里显示用户头像时，否则当用户没有设置头像时，因为没有图片数据返回而会
                // 在页面上显示一个“破图”img元素，那就难看死了！）
                if (onePixelTransparentIfNo) {
                    File onePixelTransparentAvatarImg = new File(UserAvatarDownloader.class
                            .getResource(ONE_PIXEL_TRANSPARENT_AVATAR_FILE_NAME).toURI());
                    FileDownload.download(res
                            , onePixelTransparentAvatarImg
                            , ONE_PIXEL_TRANSPARENT_AVATAR_FILE_NAME
                            , FileDownload.CONTENT_TYPE_JPEG
                            , false);
                }
            }
        } catch (Exception e) {
            LoggerFactory.getLog().warn("[HTTP]用户【" + userUid + "】的头像文件不存在，本次下载已提前结束(" + e.getMessage() + ")");
        }
    }
}
